package cc.bukkitPlugin.banitem.util;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Map;

import org.bukkit.block.Block;

import cc.bukkitPlugin.util.ClassUtil;
import cc.bukkitPlugin.util.NMSUtil;
import cc.bukkitPlugin.util.nbt.NBTUtil;

public class BINMSUtil extends NMSUtil{

    public static final Method method_CraftWorld_getTileEntityAt;
    public static final Method method_NMSTileEntity_writeToNBT;
    public static final Method method_NMSTileEntity_readFromNBT;

    static{
      //Block writeToNBT>>banitem
        Class<?> clazz_CraftWorld=ClassUtil.getCBTClass("CraftWorld");
        method_CraftWorld_getTileEntityAt=ClassUtil.getMethod(clazz_CraftWorld,"getTileEntityAt",new Class<?>[]{int.class,int.class,int.class});
        Class<?> clazz_TileEntity=method_CraftWorld_getTileEntityAt.getReturnType();
        String packetPath=NMSUtil.getClassPrefix(clazz_TileEntity.getName());
        Class<?> clazz_TileEntityChest=ClassUtil.getClass(packetPath+"TileEntityChest");
        Object tObj_TileEntityChest=ClassUtil.getInstance(clazz_TileEntityChest);
        Object tObj_NBTTagCompound=ClassUtil.getInstance(clazz_NBTTagCompound);
        ArrayList<Method> tms=ClassUtil.getUnknowMethod(clazz_TileEntity,void.class,clazz_NBTTagCompound);
        ClassUtil.invokeMethod(tObj_TileEntityChest,tms.get(0),tObj_NBTTagCompound);
        int tPos=0;
        if(tms.size()==1){  //1.9及以上
            method_NMSTileEntity_readFromNBT=tms.get(0);
            tms=ClassUtil.getUnknowMethod(clazz_TileEntity,clazz_NBTTagCompound,clazz_NBTTagCompound);
            tPos=0;
            for(Method sMethod : tms){
                if(ClassUtil.isMethodExist(clazz_TileEntityChest,sMethod)){
                    break;
                }
                tPos++;
            }
            method_NMSTileEntity_writeToNBT=tms.get(tPos);
        }else{  //1.8及以下
            if(NBTUtil.getNBTTagMapFromTag(tObj_NBTTagCompound).isEmpty())
                tPos=0;
            else tPos=1;
            method_NMSTileEntity_readFromNBT=tms.get(tPos);
            method_NMSTileEntity_writeToNBT=tms.get(1-tPos);
        }
        //Block writeToNBT -END
    }

    /**
     * 获取方块的NBT的的值域Map
     * @param pBlock 方块,可以为null
     * @return 可能为null
     */
    public static Map<String,Object> getNBTTagMapFromBlock(Block pBlock){
        return NBTUtil.getNBTTagMapFromTag(getNBTTagCompound(pBlock));
    }

    /**
     * 获取Bukkit方块的NBT标签
     * @param pBlock Bukkit方块实例
     * @return NBTTagCompound实例或者null
     */
    public static Object getNBTTagCompound(Block pBlock){
        return BINMSUtil.getTileEntityNBT(BINMSUtil.getTileEntity(pBlock),true);
    }

    /**
     * 获取指定位置方块的TileEntity
     * @param pBlock 方块
     * @return TileEntity实例或null
     */
    public static Object getTileEntity(Block pBlock){
        if(pBlock==null)
            return null;
        Object craftWorld=pBlock.getWorld();
        return ClassUtil.invokeMethod(craftWorld,BINMSUtil.method_CraftWorld_getTileEntityAt,new Object[]{pBlock.getX(),pBlock.getY(),pBlock.getZ()
        });
    }

    /**
     * 获取TileEntity实例的NBT信息
     * @param pObj TileEntity实例
     * @return NBTTagCompound实例或null
     */
    public static Object getTileEntityNBT(Object pBlockTileEntity,boolean pRemoveIdPos){
        if(!method_CraftWorld_getTileEntityAt.getReturnType().isInstance(pBlockTileEntity))
            return null;
        Object tObj_NBTTagCompound=ClassUtil.getInstance(clazz_NBTTagCompound);
        ClassUtil.invokeMethod(pBlockTileEntity,method_NMSTileEntity_writeToNBT,tObj_NBTTagCompound);
        if(pRemoveIdPos){
            Map<String,Object> tContent=NBTUtil.getNBTTagMapFromTag(tObj_NBTTagCompound);
            tContent.remove("x");
            tContent.remove("y");
            tContent.remove("z");
            tContent.remove("id");
        }
        return tObj_NBTTagCompound;
    }

}
